<template>
  <div class="room-page">
    <van-nav-bar
      fixed
      title="医生问诊室"
      left-arrow
      @click-left="$router.back()"
    />
    <room-status
      :status="orderInfo?.status!"
      :countdown="orderInfo?.countdown!"
    ></room-status>
    <van-pull-refresh v-model="isRefreshLoading" @refresh="onRefresh">
      <room-message :list="chatList"></room-message>
    </van-pull-refresh>
    <room-action
      :status="orderInfo?.status"
      @send-text="sendText"
      @send-image="sendImage"
    ></room-action>
  </div>
</template>

<script setup lang="ts">
import RoomStatus from './components/room-status.vue'
import RoomAction from './components/room-action.vue'
import RoomMessage from './components/room-message.vue'
import io, { type Socket } from 'socket.io-client'
import { baseURL } from '@/utils/request'
import { useUserStore } from '@/stores'
import { useRoute } from 'vue-router'
import type { EvaluateDoc, Message } from '@/types/room'
import { provide, ref } from 'vue'
import type { TimeMessages } from '@/types/room'
import { MsgType } from '@/enums'
import type { ConsultOrderItem, Image } from '@/types/consult'
import { getOrderDetail } from '@/api/consult'
import { nextTick } from 'vue'
import { loginByCode } from '@/api/user'

// 下拉刷新
const time = ref('')
const isRefreshLoading = ref(false)
const onRefresh = () => {
  console.log('下拉刷新')
  // 1.获取历史记录数据: 调接口 / 触发消息
  // 操作步骤： 1.1 前端触发消息  1.2 后台回复消息 复用chatMsgList 事件
  socket.emit('getChatMsgList', 20, time.value, route.query.orderId)
  // 2. 数据获取完成后，loading设置为false
  isRefreshLoading.value = false
}

const store = useUserStore()
const route = useRoute()
// 同一个服务可以同时支持https和wss: http://localhost:5173 (http ws)
// 建立连接的同时。可以携带上客户端的身份
const socket = io(baseURL, {
  auth: { token: 'Bearer ' + store.user?.token },
  query: { orderId: route.query.orderId }
})

// 提供更新消息评价的功能函数
provide('updateEvaCard', (id: string, evaDoctor: EvaluateDoc) => {
  // 根据数据项的id，匹配找到列表中的评论项 更新它的数据
  const item = chatList.value.find((item) => item.id === id)
  if (item) item.msg.evaluateDoc = evaDoctor
})

// 1. 监听连接的建立
socket.on('connect', () => {
  console.log('连接已建立')
})

// TODO 2. 发消息
const sendText = (msg: string) => {
  socket.emit('sendChatMsg', {
    from: store.user?.id,
    fromAvatar: store.user?.avatar,
    to: orderInfo.value?.docInfo?.id,
    toAvatar: orderInfo.value?.docInfo?.avatar,
    msgType: MsgType.MsgText,
    msg: {
      content: msg
    }
  })
}

// 发图片
const sendImage = (picture: Image) => {
  socket.emit('sendChatMsg', {
    from: store.user?.id,
    fromAvatar: store.user?.avatar,
    to: orderInfo.value?.docInfo?.id,
    toAvatar: orderInfo.value?.docInfo?.avatar,
    msgType: MsgType.MsgImage,
    msg: {
      picture
    }
  })
}
// 3.1 收消息： 页面初始化 接收默认消息列表
const isInitialChat = ref(true) // 标识是否是默认消息
const chatList = ref<Message[]>([])
// 收消息
socket.on('chatMsgList', ({ data }: { data: TimeMessages[] }) => {
  // 3.1.1 收默认消息 push
  // 3.1.2 收历史消息 unshift
  const target: Message[] = []
  data.forEach((item: TimeMessages, index: number) => {
    if (index === 0) {
      time.value = item.createTime //记录下默认消息列表的第一条消息的时间
    }
    target.push({
      id: item.createTime,
      msgType: MsgType.Notify, // 通用消息
      msg: { content: item.createTime },
      createTime: item.createTime
    })

    target.push(...item.items)
  })
  // 如果是默认消息  push   历史消息  unshift
  if (isInitialChat.value) {
    chatList.value.push(...target)
  } else {
    chatList.value.unshift(...target)
  }

  isInitialChat.value = false // 后续永远都是false，都不是默认消息
  nextTick(() => {
    if (isInitialChat.value) {
      // 这个回到函数，在chatList数据变化引起的页面更新后执行
      window.scrollTo(0, document.documentElement.scrollHeight)
      socket.emit(
        'updateMsgStatus',
        chatList.value[chatList.value.length - 1].id
      )
    }
  })
})

// 3.2 收消息：接收会话过程中的消息（包含自己发的+医生发的消息）
socket.on('receiveChatMsg', (Message) => {
  console.log('receiveChatMsg', Message)
  chatList.value.push(Message)
  nextTick(() => {
    // 方案一： 毕竟粗糙，预估300ms的时间，假定这个时间足够图片下载
    setTimeout(() => {
      // 这个回到函数，在chatList数据变化引起的页面更新后执行
      // dom结构确实更新成最新的了，但是dom结构中调用的网络资源未必下载完整 -> 方案一
      window.scrollTo(0, document.documentElement.scrollHeight)
      socket.emit('updateMsgStatus', Message.id)
    }, 300)
  })

  // 方案二: 准确监听最后一张图片的加载完成时,在滑动页面的滚动条
  if (Message.msgType === MsgType.MsgImage) {
    const list = [...document.querySelectorAll('.network_img')]
    const img = list[list.length - 1].querySelector('img')

    // 当图片加载完成时 执行onload事件
    img!.onload = () => {
      window.scrollTo(0, document.documentElement.scrollHeight)
      socket.emit('updateMsgStatus', Message.id)
    }
  } else {
    // 如果最后一条是文字
    window.scrollTo(0, document.documentElement.scrollHeight)
    socket.emit('updateMsgStatus', Message.id)
  }
})
socket.on('statusChange', (evt) => {
  console.log('statusChange', evt)
  // 监听到订单状态发生了变化时，重新从服务器获取订单信息
  getOrderInfo()
})

socket.on('disconnect', () => {
  console.log('断开连接')
})

// 页面打开时，获取当前这个订单的状态
const orderInfo = ref<ConsultOrderItem>()
provide('orderInfo', orderInfo) // 向 evaluate-carf.vue 组件传递orderInfo
const getOrderInfo = async () => {
  const res = await getOrderDetail({ orderId: route.query.orderId as string })
  orderInfo.value = res.data
}
getOrderInfo()
</script>

<style lang="scss" scoped>
.room-page {
  padding-top: 90px;
  padding-bottom: 60px;
  min-height: 100vh;
  box-sizing: border-box;
  background-color: var(--cp-bg);
  .van-pull-refresh {
    width: 100%;
    min-height: calc(100vh - 150px);
  }
}
</style>
